package com.security.control.app.social.openid;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.security.SocialUserDetailsService;

import java.util.HashSet;
import java.util.Set;

/**
 * @author imoot@gamil.com
 * @date 2019/1/22 0022 14:31
 * openId身份验证服务提供类
 */
public class OpenIdAuthenticationProvider implements AuthenticationProvider {

    private SocialUserDetailsService userDetailsService;

    private UsersConnectionRepository usersConnectionRepository;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //把Authentication强转为自定义的OpenIdAuthenticationToken类
        OpenIdAuthenticationToken authenticationToken = (OpenIdAuthenticationToken) authentication;

        //取出openid放入set集合中
        Set<String> providerUserIds = new HashSet<>();
        providerUserIds.add(String.valueOf(authenticationToken.getPrincipal()));
        //使用数据库处理类根据服务商id与openid取出用户id
        Set<String> userIds = usersConnectionRepository.findUserIdsConnectedTo(authenticationToken.getProviderId(),providerUserIds);
        //判断这个服务商下有没有与这个openid绑定的用户信息
        if(CollectionUtils.isEmpty(userIds) || userIds.size()!=1){
            throw new InternalAuthenticationServiceException("Unable to access user information");//无法获取用户信息
        }

        //从id结果集中取出用户id
        String userId = userIds.iterator().next();
        //使用用户id取出用户信息
        UserDetails user = userDetailsService.loadUserByUserId(userId);
        //判断有没有这个id绑定的用户信息
        if(null == user){
            throw new InternalAuthenticationServiceException("Unable to access user information");//无法获取用户信息
        }

        //使用用户权限列表和用户信息类创建OpenIdAuthenticationToken
        OpenIdAuthenticationToken authenticationResult = new OpenIdAuthenticationToken(user.getAuthorities(),user);
        //把Authentication中的用户信息设置到OpenIdAuthenticationToken中
        authenticationResult.setDetails(authenticationToken.getDetails());
        return authenticationResult;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return OpenIdAuthenticationToken.class.isAssignableFrom(authentication);
    }

    public SocialUserDetailsService getUserDetailsService() {
        return userDetailsService;
    }

    public void setUserDetailsService(SocialUserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    public UsersConnectionRepository getUsersConnectionRepository() {
        return usersConnectionRepository;
    }

    public void setUsersConnectionRepository(UsersConnectionRepository usersConnectionRepository) {
        this.usersConnectionRepository = usersConnectionRepository;
    }
}
